Skip to content

Replace custom EnvVar with corev1.EnvVar#4570

Open
anveshthakur wants to merge 13 commits intostacklok:mainfrom
anveshthakur:issue-4547
Open

Replace custom EnvVar with corev1.EnvVar#4570
anveshthakur wants to merge 13 commits intostacklok:mainfrom
anveshthakur:issue-4547

Conversation

@anveshthakur
Copy link
Copy Markdown

Summary

Fixes #
#4547

Type of change

  • Bug fix
  • New feature
  • Refactoring (no behavior change)
  • Dependency update
  • Documentation
  • Other (describe): TechDebt

Test plan

  • Unit tests (task test)
  • E2E tests (task test-e2e)
  • Linting (task lint-fix)
  • Manual testing (describe below)

Changes

File Change

Does this introduce a user-facing change?

Special notes for reviewers

Copy link
Copy Markdown
Contributor

@jerm-dro jerm-dro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! The type migration is clean and the test updates are thorough.

question: EmbeddingServerSpec.Env (at embeddingserver_types.go:76) still uses the custom EnvVar type, which prevents deleting it as #4547 suggests. Should it be included in this PR?


// convertEnvVarsFromMCPServer converts MCPServer environment variables to builder format
func convertEnvVarsFromMCPServer(envs []mcpv1alpha1.EnvVar) map[string]string {
func convertEnvVarsFromMCPServer(envs []corev1.EnvVar) map[string]string {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocker: The issue (#4547) notes that controller conversion logic should be simplified now that the types match directly. This function converts to map[string]string which is fine for the RunConfig path (JSON config file). But the same Name/Value-only copy pattern exists at mcpserver_controller.go:1142 and :1734, where it builds a new corev1.EnvVar{Name: envVar.Name, Value: envVar.Value} from what is already a corev1.EnvVar — silently dropping ValueFrom when setting env vars on the proxy Deployment pod spec.

Those two locations should be simplified to:

env = append(env, m.Spec.ResourceOverrides.ProxyDeployment.Env...)

Without this, valueFrom references on proxy env vars won't propagate to the pod spec.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good Catch ! Totally missed these
Made changes for this.

@jerm-dro

@anveshthakur
Copy link
Copy Markdown
Author

Thanks for the PR! The type migration is clean and the test updates are thorough.

question: EmbeddingServerSpec.Env (at embeddingserver_types.go:76) still uses the custom EnvVar type, which prevents deleting it as #4547 suggests. Should it be included in this PR?

#4570 didn't mention this location
I can migrate this as well to this type @jerm-dro just LMK

@github-actions github-actions bot added the size/S Small PR: 100-299 lines changed label Apr 9, 2026
@jerm-dro
Copy link
Copy Markdown
Contributor

jerm-dro commented Apr 9, 2026

Yes please, include EmbeddingServerSpec.Env in this PR so the custom EnvVar type can be fully removed.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.65%. Comparing base (b542727) to head (8dcfd7b).
⚠️ Report is 22 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4570      +/-   ##
==========================================
+ Coverage   68.60%   68.65%   +0.04%     
==========================================
  Files         515      515              
  Lines       53518    53510       -8     
==========================================
+ Hits        36718    36735      +17     
+ Misses      13958    13928      -30     
- Partials     2842     2847       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@anveshthakur
Copy link
Copy Markdown
Author

Yes please, include EmbeddingServerSpec.Env in this PR so the custom EnvVar type can be fully removed.

Heu @jerm-dro, made changes for these as well.

Copy link
Copy Markdown
Collaborator

@ChrisJBurns ChrisJBurns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-Agent Consensus Review

Agents consulted: kubernetes-expert, code-reviewer, toolhive-expert, go-security-reviewer

Consensus Summary

# Finding Consensus Severity Action
1 CRD YAML manifests not regenerated 10/10 HIGH Fix
2 convertEnvVarsFromMCPServer silently drops ValueFrom 10/10 HIGH Fix
3 EmbeddingServer controller also drops ValueFrom 9/10 HIGH Fix
4 Custom EnvVar type commented out, not deleted 9/10 MEDIUM Fix
5 No test coverage for ValueFrom scenarios 7/10 MEDIUM Fix
6 Direct pass-through expands attack surface (FieldRef) 7/10 MEDIUM Discuss
7 Deep copy import alias inconsistency 7/10 LOW Verify

Overall

The type migration from custom EnvVar to corev1.EnvVar is the right architectural direction — it eliminates a parallel type that was drifting from the Kubernetes standard and enables proper ValueFrom support for secret/configmap references. The mechanical replacement across 22 files is clean, consistent, and thorough.

However, the PR has a critical completeness gap: it changes the Go types but does not regenerate the CRD YAML manifests (task operator-manifests was not run), so the API server schema still enforces the old required: [name, value] and lacks the valueFrom field entirely. More importantly, two code paths — convertEnvVarsFromMCPServer in the RunConfig path and buildEnvVars in the EmbeddingServer controller — silently drop ValueFrom references, producing empty strings instead of the intended secret values. This creates a dangerous gap between what the CRD schema accepts and what the runtime actually handles.

The findings are blocking but straightforward to fix: regenerate CRD manifests, delete the commented-out dead code, and either reject ValueFrom with a clear error where it can't be supported (RunConfig path) or pass it through where it can (EmbeddingServer controller, which already builds []corev1.EnvVar).

Conclusion

Due to us getting v1beta1 in the next couple of days, I think it's probably wise to push this out to v1beta2. This will mean leaving this PR up for a while longer. If that's ok with you @anveshthakur then feel free to address the comments below, or you can close and keep the issue in your name and we'll slot it in nearing to v1beta2, what do you think?

Findings not attached inline

[HIGH] F1: CRD YAML manifests not regenerated (Consensus: 10/10)
The Go types changed from custom EnvVar to corev1.EnvVar but no CRD YAML files under deploy/charts/operator-crds/files/crds/ appear in this PR. Per project conventions, task operator-manifests must be run after modifying CRD types. Without this, the API server schema still has required: [name, value] and lacks the valueFrom field — the type change has no effect on cluster validation. (Raised by: kubernetes-expert, code-reviewer, toolhive-expert)

[MEDIUM] F5: No test coverage for ValueFrom scenarios (Consensus: 7/10)
All test updates use corev1.EnvVar{Name: "...", Value: "..."} — the same pattern as the old custom type. No tests verify behavior when ValueFrom is set. Add tests that confirm convertEnvVarsFromMCPServer rejects/warns on ValueFrom entries (once validation is added), and tests confirming the Deployment path properly propagates ValueFrom. (Raised by: code-reviewer, go-security-reviewer)


Generated with Claude Code

Comment on lines 431 to +440
// EnvVar represents an environment variable in a container
type EnvVar struct {
// Name of the environment variable
// +kubebuilder:validation:Required
Name string `json:"name"`

// Value of the environment variable
// +kubebuilder:validation:Required
Value string `json:"value"`
}
// type EnvVar struct {
// // Name of the environment variable
// // +kubebuilder:validation:Required
// Name string `json:"name"`

// // Value of the environment variable
// // +kubebuilder:validation:Required
// Value string `json:"value"`
// }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] F4: Custom EnvVar type commented out, not deleted (Consensus: 9/10)

Dead commented-out code should be deleted entirely. Git history preserves the original type definition if it's ever needed for reference. The zz_generated.deepcopy.go already removed the EnvVar.DeepCopyInto and EnvVar.DeepCopy methods, confirming the type is no longer used anywhere.

Delete this entire block (lines 431-440).

Raised by: kubernetes-expert, code-reviewer, toolhive-expert


// convertEnvVarsFromMCPServer converts MCPServer environment variables to builder format
func convertEnvVarsFromMCPServer(envs []mcpv1alpha1.EnvVar) map[string]string {
func convertEnvVarsFromMCPServer(envs []corev1.EnvVar) map[string]string {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] F2: convertEnvVarsFromMCPServer silently drops ValueFrom (Consensus: 10/10)

This function now accepts []corev1.EnvVar but only reads .Name and .Value. If a user specifies valueFrom: secretKeyRef: ..., the value will silently be set to an empty string. The downstream runner.RunConfig uses map[string]string and cannot support ValueFrom references.

Add validation that detects and rejects ValueFrom entries with a clear error rather than silently dropping the data.

Raised by: kubernetes-expert, code-reviewer, toolhive-expert, go-security-reviewer

Value: envVar.Value,
})
}
env = append(env, m.Spec.ResourceOverrides.ProxyDeployment.Env...)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] F6: Direct pass-through now includes FieldRef/ResourceFieldRef (Consensus: 7/10)

Nice simplification, but the full corev1.EnvVar type also includes ValueFrom.FieldRef and ValueFrom.ResourceFieldRef, which can leak node/pod metadata (hostIP, nodeName, etc.) to MCP server containers. Consider whether this expanded attack surface is acceptable, or whether validation should restrict ValueFrom to only SecretKeyRef and ConfigMapKeyRef.

Raised by: go-security-reviewer

// +listMapKey=name
// +optional
Env []EnvVar `json:"env,omitempty"`
Env []corev1.EnvVar `json:"env,omitempty"`
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] F3: EmbeddingServer controller buildEnvVars also drops ValueFrom (Consensus: 9/10)

The EmbeddingServerReconciler.buildEnvVars function at embeddingserver_controller.go:640-644 manually copies only Name/Value into new corev1.EnvVar structs, discarding ValueFrom. Since this function already returns []corev1.EnvVar, the fix is straightforward: replace the conversion loop with envVars = append(envVars, embedding.Spec.Env...) to pass through the full struct, matching the pattern used in the MCPServer proxy deployment code.

Raised by: kubernetes-expert, code-reviewer


import (
corev1 "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[LOW] F7: Generated deepcopy import alias changed from corev1 to bare v1 (Consensus: 7/10)

The import alias for k8s.io/api/core/v1 changed from the conventional corev1 to bare v1. This is generated code so it compiles fine, but suggests a different controller-gen version was used. Verify by running task operator-generate and confirming the output matches what's committed here.

Raised by: kubernetes-expert, code-reviewer, toolhive-expert

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/S Small PR: 100-299 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants